//
// * Copyright (c) 2002-2009 "Neo Technology,"
// *     Network Engine for Objects in Lund AB [http://neotechnology.com]
// *
// * This file is part of Neo4j.
// * 
// * Neo4j is free software: you can redistribute it and/or modify
// * it under the terms of the GNU Affero General Public License as
// * published by the Free Software Foundation, either version 3 of the
// * License, or (at your option) any later version.
// * 
// * This program is distributed in the hope that it will be useful,
// * but WITHOUT ANY WARRANTY; without even the implied warranty of
// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// * GNU Affero General Public License for more details.
// * 
// * You should have received a copy of the GNU Affero General Public License
// * along with this program. If not, see <http://www.gnu.org/licenses/>.
// 
namespace org.neo4j.kernel.impl.core
{

	using Direction = org.neo4j.graphdb.Direction;
	using Node = org.neo4j.graphdb.Node;
	using NotFoundException = org.neo4j.graphdb.NotFoundException;
	using Relationship = org.neo4j.graphdb.Relationship;
	using RelationshipType = org.neo4j.graphdb.RelationshipType;
	using ReturnableEvaluator = org.neo4j.graphdb.ReturnableEvaluator;
	using StopEvaluator = org.neo4j.graphdb.StopEvaluator;
	using Traverser = org.neo4j.graphdb.Traverser;
	using Order = org.neo4j.graphdb.Traverser.Order;

	internal class NodeProxy : Node
	{
		private readonly NodeManager nm;

		private readonly int nodeId;

		internal NodeProxy(int nodeId, NodeManager nodeManager)
		{
			this.nodeId = nodeId;
			this.nm = nodeManager;
		}

		public virtual long getId()
		{
			return nodeId;
		}

		public virtual void delete()
		{
			nm.getNodeForProxy(nodeId).delete();
		}

		public virtual IEnumerable <Relationship> getRelationships()
		{
			return nm.getNodeForProxy(nodeId).getRelationships();
		}

		public virtual bool hasRelationship()
		{
			return nm.getNodeForProxy(nodeId).hasRelationship();
		}

		public virtual IEnumerable <Relationship> getRelationships(Direction dir)
		{
			return nm.getNodeForProxy(nodeId).getRelationships(dir);
		}

		public virtual bool hasRelationship(Direction dir)
		{
			return nm.getNodeForProxy(nodeId).hasRelationship(dir);
		}

		public virtual IEnumerable <Relationship> getRelationships(params RelationshipType[] types)
		{
			return nm.getNodeForProxy(nodeId).getRelationships(types);
		}

		public virtual bool hasRelationship(params RelationshipType[] types)
		{
			return nm.getNodeForProxy(nodeId).hasRelationship(types);
		}

		public virtual IEnumerable <Relationship> getRelationships(RelationshipType type, Direction dir)
		{
			return nm.getNodeForProxy(nodeId).getRelationships(type, dir);
		}

		public virtual bool hasRelationship(RelationshipType type, Direction dir)
		{
			return nm.getNodeForProxy(nodeId).hasRelationship(type, dir);
		}

		public virtual Relationship getSingleRelationship(RelationshipType type, Direction dir)
		{
			return nm.getNodeForProxy(nodeId).getSingleRelationship(type, dir);
		}

		public virtual void setProperty(string key, object @value)
		{
			nm.getNodeForProxy(nodeId).setProperty(key, @value);
		}

//JAVA TO VB & C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: public Object removeProperty(String key) throws NotFoundException
		public virtual object removeProperty(string key)
		{
			return nm.getNodeForProxy(nodeId).removeProperty(key);
		}

		public virtual object getProperty(string key, object defaultValue)
		{
			return nm.getNodeForProxy(nodeId).getProperty(key, defaultValue);
		}

		public virtual IEnumerable <object> getPropertyValues()
		{
			return nm.getNodeForProxy(nodeId).getPropertyValues();
		}

		public virtual IEnumerable <string> getPropertyKeys()
		{
			return nm.getNodeForProxy(nodeId).getPropertyKeys();
		}

//JAVA TO VB & C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: public Object getProperty(String key) throws NotFoundException
		public virtual object getProperty(string key)
		{
			return nm.getNodeForProxy(nodeId).getProperty(key);
		}

		public virtual bool hasProperty(string key)
		{
			return nm.getNodeForProxy(nodeId).hasProperty(key);
		}

		public virtual int compareTo(object node)
		{
			Node n = (Node) node;
			long ourId = this.getId(), theirId = n.getId();

			if (ourId < theirId)
			{
				return -1;
			}
			else if (ourId > theirId)
			{
				return 1;
			}
			else
			{
				return 0;
			}
		}

		public override bool Equals(object o)
		{
			if (!(o is Node))
			{
				return false;
			}
			return this.getId() == ((Node) o).getId();
		}

		public override int GetHashCode()
		{
			return nodeId;
		}

		public override string ToString()
		{
			return "Node[" + this.getId() + "]";
		}

		public virtual Relationship createRelationshipTo(Node otherNode, RelationshipType type)
		{
			return nm.getNodeForProxy(nodeId).createRelationshipTo(otherNode, type);
		}

		public virtual Traverser traverse(Order traversalOrder, StopEvaluator stopEvaluator, ReturnableEvaluator returnableEvaluator, RelationshipType relationshipType, Direction direction)
		{
			return nm.getNodeForProxy(nodeId).traverse(traversalOrder, stopEvaluator, returnableEvaluator, relationshipType, direction);
		}

		public virtual Traverser traverse(Order traversalOrder, StopEvaluator stopEvaluator, ReturnableEvaluator returnableEvaluator, RelationshipType firstRelationshipType, Direction firstDirection, RelationshipType secondRelationshipType, Direction secondDirection)
		{
			return nm.getNodeForProxy(nodeId).traverse(traversalOrder, stopEvaluator, returnableEvaluator, firstRelationshipType, firstDirection, secondRelationshipType, secondDirection);
		}

		public virtual Traverser traverse(Order traversalOrder, StopEvaluator stopEvaluator, ReturnableEvaluator returnableEvaluator, params object[] relationshipTypesAndDirections)
		{
			return nm.getNodeForProxy(nodeId).traverse(traversalOrder, stopEvaluator, returnableEvaluator, relationshipTypesAndDirections);
		}
	}

}